/*
 * @Author: jiangyg email@jiangyg.com
 * @Date: 2022-10-28 20:14:30
 * @LastEditors: jiangyg email@jiangyg.com
 * @LastEditTime: 2022-12-06 21:56:10
 * @FilePath: /frontend/mall-frontend/src/router/index.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import http from "@/utils/httpRequest";
import admin from "@/utils/admin";
import { isURL } from "@/utils/index";
import { createRouter, createWebHistory } from "vue-router";
import store from "@/store";

// 根据匹配规则倒入模块
const modules = import.meta.glob(["@/views/*.vue", "@/views/*/*.vue", "@/views/*/*/*.vue", "@/views/*/*/*/*.vue", "@/views/*/*/*/*/*.vue"]);

// 定义vue文件加载规则，自动补全路径
// TODO 研究下 /src 怎么替换 @
const load = (file) => modules[`/src/views/${file}.vue`];

// TODO 404 页面

// 路由定义
let routes = [
  // 商城路由定义
  { name: "index", path: "/", component: load("index") },
  { name: "login", path: "/login", component: load("login") },
  { name: "reg", path: "/reg", component: load("reg") },
  { name: "item", path: "/item/:id", component: load("item") },
  { name: "redirect-item", path: "/item/:id", component: load("commons/redirect-item") },
  { name: "cart", path: "/cart", component: load("cart"), meta: { auth: true } },
  { name: "order", path: "/order", component: load("order"), meta: { auth: true } },
  { name: "search", path: "/search", component: load("search") },
  { name: "redirect-search", path: "/redirect-search", component: load("commons/redirect-search") },
  // 后台管理路由定义
  { name: "admin", path: "/admin", component: load("modules/admin/main"), meta: { cid: "a", auth: true }, children: [] },
  { name: "admin-login", path: "/admin/login", component: load("modules/admin/login"), meta: { cid: "a" } },
  // 全局路由定义
  { path: "/404", component: load("main/404"), name: "404" },
];

// 路由规则定义
const router = createRouter({
  routes: routes,
  scrollBehavior: () => ({ y: 0 }),
  isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
  history: createWebHistory(import.meta.env.BASE_URL),
});

/**
 * 全局前置守卫，类似路由拦截器
 *
 */
router.beforeEach((to, from, next) => {
  // 1. 设置客户端类型
  window.cid = fnDecideClientType(to);
  // 2. 后台管理路由守卫
  if (window.cid === "a") {
    fnAdminRouterBeforeEach(to, from, next);
    return;
  }
  // 3. 商城路由守卫
  if (window.cid === "m") {
    fnMemberRouterBeforeEach(to, from, next);
    return;
  }
  // 4. 其他情况则直接访问
  next();
});

/**
 * 后台管理路由守卫
 */
const fnAdminRouterBeforeEach = (to, from, next) => {
  // 1. 如果是不需要鉴权的路由，则直接访问
  if (to.matched.length > 0 && !to.meta.auth) {
    next();
    return;
  }
  // 2. 如果是 后台管理路由 且 没有登录，则跳转登录页面
  if (!admin.userInfo(undefined, false)) {
    next({ name: "admin-login" });
    return;
  }
  // 3. 如果 没有加载动态菜单 或者 没有菜单列表 的话，则加载菜单列表
  if (!router.options.isAddDynamicMenuRoutes || !admin.menuList(undefined, false)) {
    fnLoadAdminMenuData(next, to);
    return;
  }
  // 4. 其他情况则直接访问
  next();
};

/**
 * 商城路由守卫
 */
const fnMemberRouterBeforeEach = (to, from, next) => {
  // 1. 如果是不需要鉴权的路由，则直接访问
  if (to.matched.length > 0 && !to.meta.auth) {
    next();
  }
  // 2. 尝试获取会员信息
  http
    .get({
      url: "/auth/user-info",
    })
    .then(({ data }) => {
      let success = http.success(data, false);
      // 2.1 会员已登录则保存会员信息
      if (success) {
        store.commit("memberInfo", data.body);
      }
      // 2.2 如果路由需要鉴权则需要做如下处理
      if (to.meta.auth) {
        success ? next() : next({ name: "login" });
      }
    });
};

/**
 * 加载后台管理菜单数据
 * @param {*} next
 * @param {*} to
 */
const fnLoadAdminMenuData = (next, to) => {
  http
    .post({
      url: "/menu",
    })
    .then(({ data }) => {
      if (http.success(data)) {
        let body = data.body;
        let permissions = body.permissions;
        let menuList = fnMenuListAddHome(body.menus);
        admin.menuList(menuList);
        admin.permissions(permissions);
        router.options.isAddDynamicMenuRoutes = true;
        fnAddDynamicMenuRoutes(menuList);
        next({ ...to, replace: true });
      } else {
        admin.menuList([]);
        admin.permissions([]);
        next();
      }
    })
    .catch((e) => {
      console.log(`%c${e} 请求菜单列表和权限失败，跳转至登录页！`, "color:blue");
      router.push({ name: "admin-login" });
    });
};

/**
 * 添加动态(菜单)路由
 * @param {*} menuList 菜单列表
 * @param {*} routes 递归创建的动态(菜单)路由
 */
const fnAddDynamicMenuRoutes = (menuList = [], routes = []) => {
  var temp = [];
  for (var i = 0; i < menuList.length; i++) {
    let attributes = menuList[i].attributes;
    if (menuList[i].children && menuList[i].children.length >= 1) {
      temp = temp.concat(menuList[i].children);
    } else if (attributes && attributes.url && /\S/.test(attributes.url)) {
      attributes.url = attributes.url.replace(/^\//, "");
      var route = {
        path: "/admin/" + attributes.url.replace("/", "-"),
        component: null,
        name: fnCreateRouterName(attributes),
        meta: {
          id: menuList[i].id,
          name: menuList[i].name,
          iframeUrl: "",
          dynamic: attributes.hasOwnProperty("dynamic") ? attributes.dynamic : true,
          closable: attributes.hasOwnProperty("closable") ? attributes.dynamic : true,
          tab: true,
          auth: true,
          cid: "a",
        },
      };
      // url以http[s]://开头, 通过iframe展示
      if (isURL(attributes.url)) {
        route["path"] = `i-${menuList[i].id}`;
        route["name"] = `i-${menuList[i].id}`;
        route["meta"]["iframeUrl"] = attributes.url;
      } else {
        try {
          route["component"] = load(`modules/admin/${attributes.url}`) || null;
        } catch (e) {}
      }
      routes.push(route);
    }
  }
  if (temp.length >= 1) {
    fnAddDynamicMenuRoutes(temp, routes);
  } else {
    let adminRoute = router.options.routes.filter((r) => r.name === "admin")[0];
    adminRoute.children = adminRoute.children.concat(routes);
    router.addRoute(adminRoute);
    // router.addRoute({ path: '*', redirect: { name: '404' } });
    admin.dynamicRouteList(adminRoute.children || []);
  }
};

/**
 * 菜单追加首页路由
 * @param {*} menuList
 * @returns
 */
const fnMenuListAddHome = (menuList) => {
  let home = { id: "home", name: "首页", attributes: { icon: "home", url: "home", dynamic: false, closable: false } };
  return [home].concat(menuList);
};

/**
 * 生成路由名称
 * @param {*} attributes 属性
 * @returns
 */
const fnCreateRouterName = (attributes) => {
  let name = attributes.url.replace("/", "-");
  if (name.indexOf("-") == -1) {
    name = "admin-" + name;
  }
  return name;
};

/**
 * 判断路由的类型
 * @param {*} route
 * @returns
 */
const fnDecideClientType = (route) => {
  // 1. 如果meta有设置的话，客户端类型以此为准
  let cid = route.meta && route.meta.cid;
  // 2. 如果meta没有设置，则根据路径是否以 /admin 开头进行判断
  if (!cid && /^\/admin\/?.*$/.test(route.fullPath)) {
    cid = "a";
  }
  // 3. 如果以上都不满足，则为 商城路由
  return cid || "m";
};

export default router;
